package com.dx.financehy.utils;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @Author: shenzw
 * @Description: redis锁工具类
 * @Date: 2022/05/16
 */
@Service
@Slf4j
public class RedisLockUtil {
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * redis锁(用于解决消息队列消费时的幂等处理)
     *
     * @param key
     * @param value
     * @param timeout 单位为分钟
     * @return
     */
    public Boolean tryConsumeLock(String key, Object value, long timeout) {
        String str = beanToString(value);
        if (StringUtils.isAnyBlank(key, str)) {
            return false;
        }
        //默认下锁定10分钟
        if (timeout <= 0) {
            timeout = 10L;
        }
        //底层原理就是Redis的setnx方法
        Boolean isSuccess = false;
        try {
            isSuccess = redisTemplate.opsForValue().setIfAbsent("LOCK_" + key, str, timeout, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.info("redis加锁失败,请排查", e);
            isSuccess = false;
        }
        // 增加特别处理：
        if (isSuccess == null) {
            return false;
        }
        return isSuccess;
    }


    /**
     * redis锁(用于解决消息队列消费时的幂等处理)
     *
     * @param key
     * @param value
     * @param timeout 超时时间:单位秒
     * @return
     */
    public Boolean tryConsumeLockSeconds(String key, Object value, long timeout) {
        log.info("---------进入幂等校验-------");
        String str = beanToString(value);
        if (StringUtils.isAnyBlank(key, str)) {
            return false;
        }
        //默认下锁定10分钟
        if (timeout <= 0) {
            timeout = 10L;
        }
        //底层原理就是Redis的setnx方法
        Boolean isSuccess = false;
        try {
            isSuccess = redisTemplate.opsForValue().setIfAbsent("LOCK_141_" + key, str, timeout, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.info("redis加锁失败,请排查", e);
            isSuccess = false;
        }
        // 增加特别处理：
        if (isSuccess == null) {
            return false;
        }
        return isSuccess;

    }

    private <T> String beanToString(T value) {
        if (value == null) {
            return null;
        }
        Class<?> clazz = value.getClass();
        if (clazz == int.class || clazz == Integer.class) {
            return "" + value;
        } else if (clazz == String.class) {
            return (String) value;
        } else if (clazz == long.class || clazz == Long.class) {
            return "" + value;
        } else {
            return JSON.toJSONString(value);
        }
    }

}
